import os
import re
import sys
import time
import requests
import ruledesc
import k8sclient
from flask import request, Response, jsonify, redirect, url_for
from flask import Flask, send_file, abort, render_template

app = Flask(__name__)

RULES_PATH = "/uniwaf-config/rules/"

def check_file_state(file_path):
  with open(file_path, 'r') as file:
    for line in file:
      if line.strip() and not line.strip().startswith('#@'):
        return '0'  # 该文件包含不以#@开头的行
  return '1'  # 该文件所有行都以#@开头

@app.route('/api/extend/config/show', methods=['POST'])
def extend_config_show():
  # 从请求体中获取 size 和 page 参数
  request_data = request.get_json()
  size = request_data.get('size', 10)
  page = request_data.get('page', 1)
  
  # 获取所有 .conf 结尾的文件
  files = [f for f in os.listdir(RULES_PATH) if f.endswith('.conf')]
  
  # 分页处理
  start = (page - 1) * size
  end = start + size
  paged_files = files[start:end]
  
  # 构造响应数据
  data = []
  for f in paged_files:
    file_path = os.path.join(RULES_PATH, f)
    state = check_file_state(file_path)
    data.append({"name": f, "state": state, "desc": ruledesc.ruledict[f]['describe']})
  
  response_data = {
    "code": "200",
    "msg": "操作成功",
    "data": {
      "data": data,
      "count": len(files)
    },
    "success": True
  }
  
  return jsonify(response_data)

@app.route('/api/extend/config/save', methods=['POST'])
def extend_config_save():
  request_data = request.get_json()
  file_name = request_data.get('name')
  state = request_data.get('state')
  
  file_path = os.path.join(RULES_PATH, file_name)
  
  if not os.path.exists(file_path):
    return jsonify({"code": "404", "msg": "文件未找到", "success": False}), 404
  
  with open(file_path, 'r') as file:
    lines = file.readlines()

  if str(state) == '0': # 启用文件：去掉所有行前面的#@
    lines = [line.replace("#@", "", 1) if line.startswith("#@") else line for line in lines]
  elif str(state) == '1': # 禁用文件：给所有行前面加上#@
    lines = ['#@' + line for line in lines]
  
  # 更改写入PVC
  with open(file_path, 'w') as file:
    file.writelines(lines)
  
  # 重启uniwaf进程
  k8sclient.restart_daemonset('uniserver', 'uniwaf')
  k8sclient.restart_daemonset('uniserver', 'uniwaf-proxy')

  return jsonify({"code": "200", "msg": "操作成功", "success": True})

@app.route('/api/extend/config/msConf', methods=['GET'])
def extend_config_ms_show():
  # 查询命令
  command = k8sclient.get_daemonset_command('uniserver', 'uniwaf')
  uniwaf_command = next((cmd for cmd in command if 'uniwaf' in cmd), None)
  print(f'get uniwaf_command {uniwaf_command}')

  # 使用正则表达式匹配参数
  listenport_match = re.search(r"-l (\d+)", uniwaf_command)
  confpath_match = re.search(r'msconf=([^\s]+)', uniwaf_command)
  alertport_match = re.search(r"-s ([^\s;]+)", uniwaf_command)

  # 提取匹配的值并赋值给变量
  listenport = listenport_match.group(1) if listenport_match else None
  confpath = confpath_match.group(1) if confpath_match else None
  alertport = alertport_match.group(1) if alertport_match else None

  response_data = {
    "code": "200",
    "msg": "操作成功",
    "data": {
      "path": confpath,
      "port": listenport,
      "warnPath": alertport,
      "id": "66680686204fa6364510b3e1"
    },
    "success": True
  }

  return jsonify(response_data)

@app.route('/api/extend/config/msSave', methods=['POST'])
def extend_config_ms_save():
  # 获取数据
  request_data = request.get_json()
  confpath = request_data.get('path')
  listenport = request_data.get('port')
  alertport = request_data.get('warnPath')

  # 查询命令
  command = k8sclient.get_daemonset_command('uniserver', 'uniwaf')
  uniwaf_command = next((cmd for cmd in command if 'uniwaf' in cmd), None)
  print(f'get uniwaf_command {uniwaf_command}')

  # 替换参数的值
  uniwaf_command = f'uniwaf -a -l {listenport} -c {confpath} -s {alertport}; sleep 88888888888888'

  # 打印新的命令
  command[2] = uniwaf_command
  print(f"set command {command}")

  # 应用到daemonset
  k8sclient.set_daemonset_command('uniserver', 'uniwaf', command)

  return jsonify({"code": "200", "msg": "操作成功", "success": True})

@app.route('/api/extend/config/uniwafProxyShow', methods=['GET'])
def extend_config_uniwaf_proxy_show():
  # 查询命令
  envlist = k8sclient.get_daemonset_env('uniserver', 'uniwaf-proxy')
  print(f'get uniwaf proxy env {envlist}')

  port = server = backend = None

  # 查找环境变量
  for env in envlist:
    env_dict = env.to_dict()
    if env_dict['name'] == 'LISTEN_PORT': port = env_dict['value']
    elif env_dict['name'] == 'SERVER_NAME': server = env_dict['value']
    elif env_dict['name'] == 'BACKEND': backend = env_dict['value']

  # 判断文件内容中是否包含"deny"，包含为拦截
  state = 'alertOnly'
  with open('/uniwaf-config/uniwaf-proxy.conf', 'r') as file:
    content = file.read()
  if 'deny' in content: state = 'alertAndDeny'

  response_data = {
    "code": "200",
    "msg": "操作成功",
    "data": {
      "port": port,
      "server": server,
      "backend": backend,
      "state": state,
      "id": "66680686204fa6364510b3e1"
    },
    "success": True
  }

  return jsonify(response_data)

@app.route('/api/extend/config/uniwafProxySave', methods=['POST'])
def extend_config_uniwaf_proxy_save():
  # 获取数据
  request_data = request.get_json()
  port = request_data.get('port')
  server= request_data.get('server')
  backend = request_data.get('backend')
  state = request_data.get('state')

  # 查询环境变量
  envlist = k8sclient.get_daemonset_env('uniserver', 'uniwaf-proxy')

  # 替换环境变量
  result_list = []
  for env in envlist:
    env_dict = env.to_dict()
    if env_dict['name'] == 'LISTEN_PORT': env_dict['value'] = port
    elif env_dict['name'] == 'SERVER_NAME': env_dict['value'] = server
    elif env_dict['name'] == 'BACKEND': env_dict['value'] = backend
    result_list.append(env_dict)

  # 保存是否拦截到配置文件
  with open('/uniwaf-config/uniwaf-proxy.conf', 'w') as file:
    if state == 'alertAndDeny':
      file.write('SecDefaultAction "phase:1,log,auditlog,deny,status:403"\n')
      file.write('SecDefaultAction "phase:2,log,auditlog,deny,status:403"\n')
    elif state == 'alertOnly':
      file.write('SecDefaultAction "phase:1,nolog,auditlog,pass"\n')
      file.write('SecDefaultAction "phase:2,nolog,auditlog,pass"\n')

  # 应用到daemonset
  k8sclient.set_daemonset_env('uniserver', 'uniwaf-proxy', result_list)

  # 重启uniwaf进程
  k8sclient.restart_daemonset('uniserver', 'uniwaf-proxy')

  return jsonify({"code": "200", "msg": "操作成功", "success": True})

@app.route('/up-install/<filename>')
def up_install(filename):
  directory = os.path.join(os.getcwd(), '/uniproxy')
  filepath = os.path.join(directory, filename)

  # 检查文件是否存在
  if not os.path.isfile(filepath):
    abort(404)  # 如果文件不存在，返回 404 错误

  # 提供文件下载
  return send_file(filepath, as_attachment=True)

@app.route('/up-install/centos6/<filename>')
def up_install_centos6(filename):
  directory = os.path.join(os.getcwd(), '/uniproxy/centos6')
  filepath = os.path.join(directory, filename)

  # 检查文件是否存在
  if not os.path.isfile(filepath):
    abort(404)  # 如果文件不存在，返回 404 错误

  # 提供文件下载
  return send_file(filepath, as_attachment=True)

@app.route('/up-install', methods=['GET', 'POST'])
def up_upload():
  directory = os.path.join('/uniproxy')
  if request.method == 'GET':
    file_list = []
    for filename in os.listdir(directory):
      filepath = os.path.join(directory, filename)
      if os.path.isfile(filepath):
        file_info = {
          'name': filename,
          'size': os.path.getsize(filepath),
          'mtime': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(os.path.getmtime(filepath)))
        }
        file_list.append(file_info)
    return render_template('upload.html', file_list=file_list)
  elif request.method == 'POST':
    upload_file = request.files['file']
    if upload_file:
      filename = upload_file.filename
      upload_file.save(os.path.join(directory, filename))
      return redirect(url_for('up_upload'))
    return 'No file uploaded.', 400

@app.route('/up-install/centos6', methods=['GET', 'POST'])
def up_upload_centos6():
  directory = os.path.join('/uniproxy/centos6')
  if request.method == 'GET':
    file_list = []
    for filename in os.listdir(directory):
      filepath = os.path.join(directory, filename)
      if os.path.isfile(filepath):
        file_info = {
          'name': filename,
          'size': os.path.getsize(filepath),
          'mtime': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(os.path.getmtime(filepath)))
        }
        file_list.append(file_info)
    return render_template('upload.html', file_list=file_list)

@app.route('/up-install/upload-login-logo', methods=['POST'])
def upload_login_logo():
  if 'login_logo' not in request.files:
    return 'No file part', 400
  file = request.files['login_logo']
  if file.filename == '':
    return 'No selected file', 400
  if file:
    filename = 'logo.png'
    file.save(os.path.join('/uniproxy', filename))
    return redirect(url_for('up_upload'))

@app.route('/up-install/upload-nav-logo', methods=['POST'])
def upload_nav_logo():
  if 'nav_logo' not in request.files:
    return 'No file part', 400
  file = request.files['nav_logo']
  if file.filename == '':
    return 'No selected file', 400
  if file:
    filename = 'logo-nav.png'
    file.save(os.path.join('/uniproxy', filename))
    return redirect(url_for('up_upload'))

if __name__ == '__main__':
  port = int(sys.argv[1])
  app.run(host='0.0.0.0', port=port)

